package cn.sfa.service.routine;

import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import microsoft.exchange.webservices.data.Appointment;
import microsoft.exchange.webservices.data.BodyType;
import microsoft.exchange.webservices.data.ExchangeCredentials;
import microsoft.exchange.webservices.data.ExchangeService;
import microsoft.exchange.webservices.data.ExchangeVersion;
import microsoft.exchange.webservices.data.FindItemsResults;
import microsoft.exchange.webservices.data.ItemId;
import microsoft.exchange.webservices.data.MessageBody;
import microsoft.exchange.webservices.data.PropertySet;
import microsoft.exchange.webservices.data.SendInvitationsMode;
import microsoft.exchange.webservices.data.ServiceLocalException;
import microsoft.exchange.webservices.data.StringList;
import microsoft.exchange.webservices.data.WebCredentials;
import microsoft.exchange.webservices.data.WellKnownFolderName;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import cn.sfa.common.utils.ConfigUtil;
import cn.sfa.entity.routine.SalePrivateAffair;
import cn.sfa.entity.system.SaleSysCode;
import cn.sfa.service.system.SaleSysCodeService;

public class ExChangeCalendarService {

	@Autowired
	SaleSysCodeService saleSysCodeService;
	static Logger log = LoggerFactory.getLogger(CalendarService.class);
	private static String ewsUrl = "";
	private static String domain = "";

	static {

		try {
			Configuration config = ConfigUtil
					.getXmlConfig(ExChangeCalendarService.class
							.getClassLoader().getResource("/sys_config.xml")
							.getPath());
			ewsUrl = config.getString("ews-url");
			log.info("ewsUrl============" + ewsUrl);
			domain = config.getString("emailDomain");
		} catch (ConfigurationException e) {
			throw new RuntimeException(e + "配置文件初始化ews-url错误");
		}

	}

	public ExchangeService StartExchange(String username, String pwd) {

		ExchangeService service = new ExchangeService(
				ExchangeVersion.Exchange2010);
		ExchangeCredentials credentials = new WebCredentials(username, pwd);
		service.setCredentials(credentials);
		try {
			service.setUrl(new URI(ewsUrl));
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return service;
	}

	public Map getCalendar(int year, int month, String username, String pwd) {
		try {
			ExchangeService service = this.StartExchange(username, pwd);
			SimpleDateFormat dateFormat = new SimpleDateFormat(
					"yyyy-MM-dd HH:mm:ss");
			Date startTime = dateFormat.parse(year + "-" + month
					+ "-01 00:00:00");
			Date endTime = dateFormat.parse(year + "-" + (month + 1)
					+ "-01 00:00:00");
			Date tmpDate = new Date(endTime.getTime() - 1);
			endTime = dateFormat.parse(dateFormat.format(tmpDate));

			// 因为要转换成0时区,所以需要减掉8个小时
			startTime = new Date(startTime.getTime() - 28800000);
			endTime = new Date(endTime.getTime() - 28800000);

			microsoft.exchange.webservices.data.CalendarView view = new microsoft.exchange.webservices.data.CalendarView(
					startTime, endTime);
			FindItemsResults<Appointment> appointment = service
					.findAppointments(WellKnownFolderName.Calendar, view);

			if (appointment.getTotalCount() > 0) {
				service.loadPropertiesForItems(appointment,
						PropertySet.FirstClassProperties);
			} else {
				return new HashMap();
			}

			Map calendar = new HashMap();
			for (Appointment it : appointment.getItems()) {

				// 根据时区的差异更新开始时间
				Date newStartTime = new Date(it.getStart().getTime()
						+ this.getTimeOffSet(it.getTimeZone()));
				it.setStart(newStartTime);

				// 根据时区的差异更新结束时间
				Date newEndTime = new Date(it.getEnd().getTime()
						+ this.getTimeOffSet(it.getTimeZone()));
				it.setEnd(newEndTime);

				// 得到这个约会的 日 部分
				GregorianCalendar temp = new GregorianCalendar();
				temp.setTime(newStartTime);
				int day = temp.get(Calendar.DAY_OF_MONTH);
				// 把day作为key 把当日的约会放进对于的value里面去
				if (!calendar.keySet().contains(day)) {
					calendar.put(day, new ArrayList<Appointment>());
				}
				ArrayList<Appointment> appList = (ArrayList<Appointment>) calendar
						.get(day);
				appList.add(it);
			}
			// System.out.println(calendar.keySet().size());
			return calendar;

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/*
	 * 根据id获取约会信息
	 */
	public Appointment getAppointmentByID(String id, String username, String pwd) {
		ExchangeService service = this.StartExchange(username, pwd);
		try {
			Appointment message = Appointment.bind(service, new ItemId(id));
			return message;
		} catch (Exception e) {
			System.out.println(e.getMessage());
			return null;
		}
	}

	/*
	 * 根据时区字符串计算当前时区的offSet
	 */
	public long getTimeOffSet(String timeZoneName) {
		// 正则表达式
		Pattern pattern = Pattern
				.compile("\\(UTC([+-]?)((\\d{1,2}):(\\d{1,2}))?\\)");
		Matcher matcher = pattern.matcher(timeZoneName);
		if (matcher.find()) {
			// 如果是0时区则返回0
			if (matcher.group(0) == "(UTF)") {
				return 0;
			}
			// 否则返回相应的offSet
			int hour = Integer.valueOf(matcher.group(3));
			int minutes = Integer.valueOf(matcher.group(4));

			int offSet = (hour * 60 + minutes) * 60 * 1000;
			// 正负时区
			if (matcher.group(1).equals("+")) {
				return offSet;
			} else {
				return offSet * -1;
			}
		} else {
			// 如果找不到 返回默认的 offset 8个小时;
			return 8 * 60 * 60 * 1000;
		}

		// 例子:
		// 时区(UTC+08:00)北京，重庆，香港特别行政区，乌鲁木齐
		// 匹配结果
		// 0 (UTC+08:00)
		// 1 +
		// 2 08:00
		// 3 08
		// 4 00

	}

	/*
	 * 获取具体某天的约会列表
	 */
	public List<Appointment> getCalendarByDay(int year, int month, int day,
			String username, String pwd) {
		try {
			ExchangeService service = this.StartExchange(username, pwd);
			SimpleDateFormat dateFormat = new SimpleDateFormat(
					"yyyy-MM-dd HH:mm:ss");
			Date startTime = dateFormat.parse(year + "-" + month + "-" + day
					+ " 00:00:00");
			Date endTime = dateFormat.parse(year + "-" + month + "-"
					+ (day + 1) + " 00:00:00");
			Date tmpDate = new Date(startTime.getTime());
			startTime = dateFormat.parse(dateFormat.format(tmpDate));
			tmpDate = new Date(endTime.getTime() - 1);
			endTime = dateFormat.parse(dateFormat.format(tmpDate));

			System.out
					.println("时间条件1========================================================================");
			System.out.println(startTime + "---" + endTime);
			// 因为要转换成0时区,所以需要减掉8个小时
			startTime = new Date(startTime.getTime() - 28800000);
			endTime = new Date(endTime.getTime() - 28800000);

			System.out
					.println("时间条件2========================================================================");
			System.out.println(startTime + "---" + endTime);
			microsoft.exchange.webservices.data.CalendarView view = new microsoft.exchange.webservices.data.CalendarView(
					startTime, endTime);

			FindItemsResults<Appointment> appointment = service
					.findAppointments(WellKnownFolderName.Calendar, view);

			if (appointment.getTotalCount() > 0) {
				service.loadPropertiesForItems(appointment,
						PropertySet.FirstClassProperties);
			} else {
				return new ArrayList<Appointment>();
			}

			List<Appointment> dayCalendar = new ArrayList<Appointment>();
			StringList categories = new StringList();
			categories.add("其他");
			for (Appointment it : appointment.getItems()) {
				System.out.println(it.getStart() + "---" + it.getEnd());
				// 根据时区的差异更新开始时间
				Date newStartTime = new Date(it.getStart().getTime()
						+ this.getTimeOffSet(it.getTimeZone()));
				it.setStart(newStartTime);

				// 根据时区的差异更新结束时间
				Date newEndTime = new Date(it.getEnd().getTime()
						+ this.getTimeOffSet(it.getTimeZone()));
				it.setEnd(newEndTime);
				System.out.println(it.getStart() + "---" + it.getEnd());
				System.out.println("-------------");

				// 把全天事件排除掉
				startTime = dateFormat.parse(year + "-" + month + "-" + day
						+ " 00:00:00");
				startTime = new Date(startTime.getTime()
						- (24 * 60 * 60 * 1000));
				if (it.getStart().getTime() == startTime.getTime()
						&& it.getIsAllDayEvent()) {
					continue;
				}

				try {
					if (it.getCategories().getSize() == 0) {
						it.setCategories(categories);
					}
					dayCalendar.add(it);
				} catch (ServiceLocalException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return dayCalendar;
		} catch (Exception e) {
			System.out.println(e.getMessage());
			return new ArrayList<Appointment>();
		}
	}

	public boolean createAppointment(SalePrivateAffair model, String userName,
			String pwd) { 

		ExchangeService service = this.StartExchange(userName, pwd);

		try {
			Appointment appointment = new Appointment(service);

			// 设置时间
			Date startDate = new Date(
					(model.getMarkDate().getTime() - 28800000));
			Date endDate = new Date(
					(model.getMarkDate().getTime() + 1800000 - 28800000));

			appointment.setStart(startDate);
			appointment.setEnd(endDate);

			// 设置标题和内容
			appointment.setSubject(model.getAffairItem());
			appointment.setBody(new MessageBody(BodyType.HTML, model
					.getAffairContent()));

			// 设置收件人
			// appointment.getRequiredAttendees().add(userName + "@" + domain);

			// 设置分类名
			StringList categories = new StringList(); 
			SaleSysCode syscode = saleSysCodeService.getSaleSysCode(model
					.getAffairType());
			categories.add(syscode.equals(null) ? "其他" : syscode.getChnName());
			appointment.setCategories(categories);

			appointment.save(SendInvitationsMode.SendToAllAndSaveCopy);
			return true;
		} catch (Exception ex) {
			log.error(ex.getMessage());
			return false;
		}
	}

}
